#include "main_form.h"
#include "ui_main_form.h"

#include <QDomDocument>
#include <QDomElement>
#include <QMessageBox>
#include <QListWidgetItem>

#include "row_text_templates.h"
#include "model.h"
#include "delegate.h"
#include "from_xml.h"


MainForm::MainForm(QWidget* parent):
    QWidget(parent),
    _ui(new Ui::MainForm()),
    _model(NULL)
{
    _ui->setupUi(this);
    connect(
        _ui->btn_commit_format, SIGNAL(clicked()),
        this, SLOT(commitFormat())
    );
    connect(
        _ui->w_data, SIGNAL(itemChanged(QListWidgetItem*)),
        this, SLOT(dataChanged(QListWidgetItem*))
    );
    
    _ui->w_format->setFontFamily("Courier");
    
    _ui->w_format->setPlainText(
        tr(
            "<?xml version='1.0' encoding='UTF-8'?>\n"
            "<model>\n"
            "    <rows>\n"
            "        <header title='Биты:'/>\n"
            "        <word title=''>\n"
            "            <field title='Порт отправителя' bits='31:16'/>\n"
            "            <field title='Порт получателя' bits='15:0'/>\n"
            "        </word>\n"
            "        <word title='Порядковый номер'/>\n"
            "        <word title='Номер подтверждения'/>\n"
            "        <word title=''>\n"
            "            <field title='Длина заголовка' bits='31:28'/>\n"
            "            <field title='Неиспользуемое поле' bits='27:22'/>\n"
            "            <field title='URG' bits='21'/>\n"
            "            <field title='ACK' bits='20'/>\n"
            "            <field title='PSH' bits='19'/>\n"
            "            <field title='RST' bits='18'/>\n"
            "            <field title='SYN' bits='17'/>\n"
            "            <field title='FIN' bits='16'/>\n"
            "            <field title='Размер окна' bits='15:0'/>\n"
            "        </word>\n"
            "        <word title=''>\n"
            "            <field title='Контрольная сумма' bits='31:16'/>\n"
            "            <field title='Указатель на срочные данные' bits='15:0'/>\n"
            "        </word>\n"
            "    </rows>\n"
            "    <columns>\n"
            "        <column title='Байт 3' bits='31:24'/>\n"
            "        <column title='Байт 2' bits='23:16'/>\n"
            "        <column title='Байт 1' bits='15:8'/>\n"
            "        <column title='Байт 0' bits='7:0'/>\n"
            "    </columns>\n"
            "</model>\n"
        )
    );
    
    QAbstractItemDelegate* old_delegate = _ui->w_bitwin->itemDelegate();
    _ui->w_bitwin->setItemDelegate(new BitWin::Delegate());
    delete old_delegate;
    
    addNewItem("0xEDBA0BAB");
    addNewItem("0xA0F1823D");
    addNewItem("0x11111111");
    addNewItem("0x22222222");
    addNewItem("0xFFFFFFFF");
    addNewItem();
    commitData();
    commitFormat();
}

MainForm::~MainForm()
{
    delete _ui->w_bitwin->itemDelegate();
    delete _ui;
}

void MainForm::commitData()
{
    QList<unsigned> data_list;
    for (int i = 0; i < (_ui->w_data->count() - 1); ++i)
        data_list
            << _ui->w_data->item(i)->data(Qt::DisplayRole).toString().toUInt(NULL, 0)
        ;
    
    if (_model)
        _model->setUp<BitWin::PRowTextMaker::FromIntegral>(
            data_list.begin(), data_list.end()
        );
}

void MainForm::commitFormat()
{
    QDomDocument doc;
    QString err_msg;
    int err_line;
    int err_column;
    
    if (!doc.setContent(_ui->w_format->toPlainText(), &err_msg, &err_line, &err_column))
    {
        QMessageBox msg_box;
        msg_box.setText(
            tr("Ошибка разбора XML-документа в строке %1 колонке %2\n Диагноз:\n%3")
            .arg(err_line)
            .arg(err_column)
            .arg(err_msg)
        );
        msg_box.setIcon(QMessageBox::Critical);
        msg_box.exec();
    }
    else
    {
        BitWin::Model* new_model = BitWin::FromXml::makeModel(doc.documentElement());
        if (new_model)
        {
            _ui->w_bitwin->setModel(new_model);
            delete _model;
            _model = new_model;
            commitData();
        }
    }
}

void MainForm::dataChanged(QListWidgetItem* item)
{
    int row = _ui->w_data->row(item);
    if (row < 0)
        return;
    
    bool is_last = ((_ui->w_data->count() - 1) == row);
    bool is_empty = item->data(Qt::DisplayRole).toString().simplified().isEmpty();
    
    if (is_empty && (!is_last))
        delete _ui->w_data->takeItem(row);
    else if ((!is_empty) && (is_last))
        addNewItem();
    
    commitData();
}

void MainForm::addNewItem(const QString& data)
{
    QListWidgetItem* new_item = new QListWidgetItem(data);
    new_item->setFlags(new_item->flags() | Qt::ItemIsEditable);
    _ui->w_data->addItem(new_item);
}
